package org.xq.shop.maxaishop.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.xq.shop.maxaishop.conf.XqConstants;
import org.xq.shop.maxaishop.entity.XqCommodity;
import org.xq.shop.maxaishop.entity.XqCorder;
import org.xq.shop.maxaishop.entity.XqCustomer;
import org.xq.shop.maxaishop.entity.XqSpkie;
import org.xq.shop.maxaishop.service.XqCommodityService;
import org.xq.shop.maxaishop.service.XqCorderService;
import org.xq.shop.maxaishop.service.XqCustomerService;
import org.xq.shop.maxaishop.service.XqSpkieService;
import org.xq.shop.maxaishop.util.*;
import sy.mqapi.Producer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * (XqCorder)表控制层
 *
 * @author makejava
 * @since 2021-06-17 19:44:30
 */
@Slf4j
@Api( tags = "订单管理与操作")
@RestController
@RequestMapping("xqCorder")
public class XqCorderController {
    /**
     * 服务对象
     */
    @Resource
    private XqCorderService xqCorderService;
    @Resource
    private  XqCommodityService xqCommodityService;
    @Resource
    private XqCustomerService xqCustomerService;
    @Resource
    private XqSpkieService xqSpkieService;


    @Resource
    RedisTemplate redisTemplate;

    @Resource
    Producer producer;

    /**
     * 获取订单号
     * @param uid
     * @return
     */
    @ApiOperation("生成订单号")
    @ApiImplicitParam(name="uid",value="用户id",required=true,paramType="query",dataType="String")
    @PostMapping("dingDan")
    public String dingDan(String uid){
        String orderIdByTime = GenerateNum.getOrderIdByTime();
        return orderIdByTime+uid;
    }
    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @ApiOperation("根据主键查询单个订单信息")
    @ApiImplicitParam(name = "id", value = "商品id", required=true,paramType="query" )
    @GetMapping("selectOne")
    public XqCorder selectOne(Integer id) {
        return this.xqCorderService.queryById(id);
    }

    /**
     *生成普通订单.
     * @param xqCorder
     * @return
     */
    @ApiOperation("生成普通订单")
    @PostMapping("insert")
    public Map insert(@RequestBody XqCorder xqCorder){
        System.out.println(xqCorder);
        int insert = xqCorderService.insert(xqCorder);
        if (insert==1) {
            return JsonRes.success("成功下单");
        } else {
            return JsonRes.failure(null);
        }
    }

    /**
     * 生成秒杀订单
     * @param xqCorder
     * @return
     */
    @ApiOperation("生成秒杀订单")
    @PostMapping("insert1")
    public Map insert1(@RequestBody XqCorder xqCorder){

//        xqCorder.setOrnumber(GenerateNum.getOrderNo());
        //同一用户重复下单问题, key = 秒杀ID + 客户ID
        Long increment = redisTemplate.opsForValue().increment(XqConstants.MAXAISHOP_SPKIE_REPEAT_ORDER + xqCorder.getSpkieId()+ ":" + xqCorder.getCustomerId());
        if (increment > 1) {
            log.error("您已下单, 请不要重复下单. uid = {}", xqCorder.getCustomerId());
            return JsonRes.failure("您已下单, 请不要重复下单.", -1);
        }

        //redis中的剩余库存
        String leftStock = (String) redisTemplate.opsForValue().get(XqConstants.MAXAISHOP_SPKIE_STORE + xqCorder.getSpkieId() + ":" + xqCorder.getCid());
        if (leftStock != null && Integer.parseInt(leftStock)>0) { //如果redis没有载入库存, 减mysql库存
        } else {
            System.out.println("商品已售罄, 下单失败.==" + leftStock);
            return JsonRes.failure("商品已售罄, 下单失败.", -1);
        }
/*
        String queueName = orderConsumer.getQueueName();
        RedisQueueMessage redisQueueMessage = new RedisQueueMessage(JSON.toJSONString(xqCorder));
        //发送消息队列
        redisQueueProducer.sendMessage(queueName, redisQueueMessage);
*/

        try {
            //发送MQ消息
            producer.sendMsg(JSON.toJSONString(xqCorder));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息异常:{}", e.getMessage());
            // 尝试恢复库存
            redisTemplate.opsForValue().increment(XqConstants.MAXAISHOP_SPKIE_STORE + xqCorder.getSpkieId() + ":" + xqCorder.getCid());
            // 尝试恢复用户下单计数
            redisTemplate.opsForValue().decrement(XqConstants.MAXAISHOP_SPKIE_REPEAT_ORDER + xqCorder.getSpkieId()+ ":" + xqCorder.getCustomerId());
            return JsonRes.failure("下单失败, 消息发送失败", -1);
        }

        //记录下单状态, 2=已下单, 1=下单中, -1=下单失败, 缓存30分钟
        redisTemplate.opsForValue().set(XqConstants.MAXAISHOP_SPKIE_ORDER_STATUS + xqCorder.getSpkieId()+ ":" + xqCorder.getCustomerId(), "1", 30, TimeUnit.MINUTES);
        log.info("成功下单, 正在排队中... {} " , xqCorder.getOrnumber());
        return JsonRes.success("成功下单, 正在排队中...", 1);
    }

    /**
     * 查询下单结果
     * @param xqCorder   订单对象,  主要传秒杀ID,商品ID和用户ID
     * @return 返回 2=已下单, 1=下单中, -1=下单失败
     */
    @ApiOperation("查询下单结果")
    @PostMapping("getOrderResult")
    public Map getOrderResult(@RequestBody XqCorder xqCorder) {
        System.out.println("订单信息"+xqCorder);
        Object o = redisTemplate.opsForValue().get(XqConstants.MAXAISHOP_SPKIE_ORDER_STATUS + xqCorder.getSpkieId() + ":" + xqCorder.getCustomerId());
        Map success = null;
        //数据库中已下单
        if (o == null) {
            return JsonRes.failure("请先下单!", 100);
        } else if ("1".equals(o.toString())) {
            return JsonRes.success("正在排队中, 请稍等!", 1);
        } else if ("2".equals(o.toString())) {
            return JsonRes.success("下单成功!", 2);
        } else {
            return JsonRes.success("下单失败!",-1);
        }
    }

    /**
     * 普通订单
     * @param page
     * @param limit
     * @return
     */
    @ApiOperation("普通订单列表接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name="page",value="页面",required=true,paramType="query"),
            @ApiImplicitParam(name="limit",value="每页行数",required=true,paramType="query"),
    })
    @GetMapping("selectAll")
    public Result<XqCorder> selectAll(Integer page, Integer limit,String u){
        int start = (page-1)*limit;
        Result<XqCorder> result = new Result<XqCorder>();
        System.out.println(u);
        if (u==null){
            List<XqCorder> xqCorders = this.xqCorderService.selectAll(start, limit);
            int count = this.xqCorderService.selectCount();
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }else if (u=="") {
            List<XqCorder> xqCorders = this.xqCorderService.selectAll(start, limit);
            int count = this.xqCorderService.selectCount();
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }else {
            List<XqCorder> xqCorders = this.xqCorderService.selByUname(u,start, limit);
            int count = this.xqCorderService.selCount(u);
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }

    }

    /**
     * 查询订单
     * @param uid
     * @return
     */
    @ApiOperation("用户查看订单")
    @ApiImplicitParam(name="uid",value="用户名",required=true,paramType="query")
    @PostMapping("selectByUname")
    public List<XqCorder> selectByUname(int uid) {
       return  this.xqCorderService.selectByUname(uid);
    }


    /**
     * 秒杀订单
     * @param page
     * @param limit
     * @return
     */
    @ApiOperation("秒杀订单列表接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name="page",value="页面",required=true,paramType="query"),
            @ApiImplicitParam(name="limit",value="每页行数",required=true,paramType="query"),
    })
    @GetMapping("selectMs")
    public Result<XqCorder> selectMs(String cname,Integer page, Integer limit){
        int start = (page-1)*limit;
        Result<XqCorder> result = new Result<XqCorder>();
        if (cname==null){
            List<XqCorder> xqCorders = this.xqCorderService.selectMs(start, limit);
            for (XqCorder x:xqCorders
                 ) {
                if (x.getSpkieNum()>=1&&x.getSpkieNum()<101){
                    x.setZk("1折");
                }else if(x.getSpkieNum()>=101&&x.getSpkieNum()<501){
                    x.setZk("5折");
                }else if (x.getSpkieNum()>=501&&x.getSpkieNum()<1001){
                   x.setZk("8折");
                }else {
                    x.setZk("原价购买");
                }
            }
            int count = this.xqCorderService.selectCountMs();
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }else if (cname=="") {
            List<XqCorder> xqCorders = this.xqCorderService.selectMs(start, limit);
            for (XqCorder x:xqCorders
            ) {
                if (x.getSpkieNum()>=1&&x.getSpkieNum()<101){
                    x.setZk("1折");
                }else if(x.getSpkieNum()>=101&&x.getSpkieNum()<501){
                    x.setZk("5折");
                }else if (x.getSpkieNum()>=501&&x.getSpkieNum()<1001){
                    x.setZk("8折");
                }else {
                    x.setZk("原价购买");
                }
            }
            int count = this.xqCorderService.selectCountMs();
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }else {
            List<XqCorder> xqCorders = this.xqCorderService.selByCname(cname,start, limit);
            for (XqCorder x:xqCorders
            ) {
                if (x.getSpkieNum()>=1&&x.getSpkieNum()<101){
                    x.setZk("1折");
                }else if(x.getSpkieNum()>=101&&x.getSpkieNum()<501){
                    x.setZk("5折");
                }else if (x.getSpkieNum()>=501&&x.getSpkieNum()<1001){
                    x.setZk("8折");
                }else {
                    x.setZk("原价购买");
                }
            }
            int count = this.xqCorderService.selCountMs(cname);
            result.setCode(200);
            result.setCount(count);
            result.setMsg("请求成功");
            result.setData(xqCorders);
            return result;
        }

    }

    /**
     * 待收货个数
     * @param uid
     * @return
     */
    @ApiOperation("查询待收货量")
    @ApiImplicitParam(name = "uid", value = "用户id", required=true,paramType="query" )
    @GetMapping("selectCountt")
    public int selectCountt(Integer uid){
        return this.xqCorderService.selectCountt(uid);
    }

    @ApiOperation("下单成功通知")
    @ApiImplicitParams({
            @ApiImplicitParam(name="uid",value="用户id",required=true,paramType="query"),
            @ApiImplicitParam(name="limit",value="秒杀id",required=true,paramType="query"),
    })
    @PostMapping("yj")
    public boolean yj(Integer uid,Integer mid,String ornumber){
        System.out.println(ornumber);
        XqCorder xqCorder = xqCorderService.selectByOrnumber(ornumber);
        XqCustomer xqCustomer = xqCustomerService.queryById(uid);
        XqSpkie xqSpkie = xqSpkieService.selectMs(mid);
       String txt ="您已下单成功\n" +
               "商品名："+xqSpkie.getMname()+"\t\t\t\n" +
               "商品："+xqSpkie.getComImg()+"\n"+
               "支付金额为￥"+xqCorder.getCprice()+"\n"+
               "请你前往订单中心查看订单信息";
        MailUtils.sendMail(xqCustomer.getCustomerEmail(),txt , "惊鸿果蔬下单成功邮件");
        return true;
    }


    /**
     * 订单支付结果查询
     * @param request
     * @param response
     * @return
     */
    @PostMapping("notifyInfo")
    public String getNotifyUrlInfo(HttpServletRequest request, HttpServletResponse response) {
        log.info("收到支付宝异步回调 start...");
        //接收参数进行校验
        Map<String, String> parameters = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        System.out.println(requestParams.toString());
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            parameters.put(key, valueStr);
        }
        //appid
        String appId = request.getParameter("app_id");
        //我们调用appPagePay方法 传入的订单编号
        String merchantOrderNo = request.getParameter("out_trade_no");
//        支付宝交易号
        String tradeNo = request.getParameter("trade_no");
        try {
            //交易状态
            String payState = request.getParameter("trade_status");
//          用户支付金额
            BigDecimal totalAmount = new BigDecimal(request.getParameter("total_amount"));
//          实收金额
            BigDecimal receiptAmount = new BigDecimal(request.getParameter("receipt_amount"));
            log.info("交易状态:{},支付金额为：{},实付金额为：{}", payState, totalAmount,receiptAmount);
            //验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(parameters, AlipayConfigInfo.alipay_public_key , "UTF-8", AlipayConfigInfo.sign_type);
//          验签  验证商户id  验证支付宝返回状态
            if (signVerified && AlipayConfigInfo.app_id.equals(appId) && "TRADE_SUCCESS".equals(payState)) {
                //你的业务参数    判断成功后给支付宝返回7个字符的success
                log.info("交易成功！！！！");
                xqCorderService.updateStatus(merchantOrderNo);

                XqCorder xqCorder = xqCorderService.selectByOrnumber(merchantOrderNo);

                XqCustomer xqCustomer = xqCustomerService.queryById(xqCorder.getCustomerId());
                XqCommodity xqCommodity = xqCommodityService.queryById(xqCorder.getCid());
                String txt ="您已下单成功\n" +
                        "商品名："+xqCorder.getCname()+"\t\t\t\n" +
                        "商品："+xqCommodity.getComImg()+"\n"+
                        "支付金额为￥"+totalAmount+"\n"+
                        "请你前往订单中心查看订单信息";
                MailUtils.sendMail(xqCustomer.getCustomerEmail(),txt , "惊鸿果蔬下单成功邮件");
                return "success";
            }
        } catch (AlipayApiException e) {
            log.error(e.getErrMsg());
            throw new RuntimeException("调用支付宝接口发生异常");
        }
        return "";
    }

    /**
     * 订单支付
     * @param cprice
     * @param cid
     * @param count
     * @param ornumber
     * @param customerId
     * @param person
     * @param address
     * @param tel
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @PostMapping("goAlipay")
    public String goAlipay(double cprice, int cid, int count, String ornumber, int customerId, String person, String address, String tel, HttpServletRequest request, HttpServletRequest response) throws Exception {

        //获得初始化的AlipayClient
        XqCommodity xqCommodity = xqCommodityService.queryById(cid);
        int insert = xqCorderService.insetPt(cprice, cid, count, ornumber, customerId, person, address, tel);
        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfigInfo.gatewayUrl,
                AlipayConfigInfo.app_id,
                AlipayConfigInfo.merchant_private_key,
                "json",
                AlipayConfigInfo.charset,
                AlipayConfigInfo.alipay_public_key,
                AlipayConfigInfo.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfigInfo.return_url);
        alipayRequest.setNotifyUrl(AlipayConfigInfo.notify_url);

        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = ornumber;
        //付款金额，必填
        String total_amount = String.valueOf(cprice);
        //订单名称，必填
        String subject = xqCommodity.getComName();
        //商品描述，可空
        String body = "用户订购商品个数："+count;

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "10m";

        //例子去官方api找
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + total_amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"body\":\"" + body + "\","
                + "\"timeout_express\":\"" + timeout_express + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");


        //请求
        String result = alipayClient.pageExecute(alipayRequest).getBody();

        return result;
    }


}
